﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
// add
using System.IO;
using System.Data;

namespace FormBase
{
    public class CDatasetKeyValue: CLastError
    {
        DataSetKeyValue mDataSetDB;
        DataSetKeyValue.TKeyValueDataTable mTableDB;
        DataSetKeyValue.TKeyValueRow mRowDB;

        DataSetKeyValue mDataSetEntry;
        DataSetKeyValue.TKeyValueDataTable mTableEntry;
        public DataSetKeyValue.TKeyValueRow mRow { get; set; }
        DataSetKeyValue.TKeyValueRow mRowBackup;

        public DataView mDataView { get; private set; }
        public string msFile { get; set; }
        public CDatasetKeyValue()
        {
            mDataSetDB = new DataSetKeyValue();
            mTableDB = mDataSetDB.TKeyValue;

            mDataSetEntry = new DataSetKeyValue();
            mTableEntry = mDataSetEntry.TKeyValue;
            mRow = mTableEntry.NewTKeyValueRow();
            mRowBackup = mTableEntry.NewTKeyValueRow();
            RowClear();
        }

        public bool Save()
        {
            if (string.IsNullOrEmpty(msFile))
            {
                SetLastError(enumErrorNo.ErrorEmpty, "Please input filename.");
                return false;
            }
            if (!Directory.Exists(Path.GetDirectoryName(msFile)))
            {
                SetLastError(enumErrorNo.ErrorNotFind, string.Format("Directory does not exist. File={0}.", msFile));
                return false;
            }
            File.WriteAllText(msFile, mDataSetDB.GetXml(), Encoding.UTF8);
            return true;
        }
        public bool SaveSchema(string sFile)
        {
            File.WriteAllText(sFile, mDataSetDB.GetXmlSchema().Replace("utf-16", "utf-8"), Encoding.UTF8);
            return true;
        }

        public bool Load()
        {
            //CProject.mLastError.ClearLastError();
            if (string.IsNullOrWhiteSpace(msFile))
            {
                SetLastError(enumErrorNo.ErrorEmpty, string.Format("Please input filename."));
                return false;
            }
            if (!File.Exists(msFile))
            {
                SetLastError(enumErrorNo.ErrorNotFind, string.Format("File does NOT exist. File={0}.", msFile));
                return false;
            }
            mDataSetDB.Clear();

            XmlReadMode mode1 = mDataSetDB.ReadXml(msFile);
            if (mTableDB.Rows.Count < 1)
            {
                SetLastError(enumErrorNo.ErrorNotFind, String.Format("Rows count < 1 in file {0}.", msFile));
                return false;
            }
            return true;
        }
        public void RowClear()
        {
            //DataSetKeyValue.TKeyValueRow RowBlank = mTableEntry.NewTKeyValueRow();
            //mRow.ItemArray = mTableEntry.NewTKeyValueRow().ItemArray;
            // Primary key can't be DBNull!
            //mRow.FKey = string.Empty;
            
            // DBNull fields will cause many problem on runtime!
            // so, we clear by setting the init value for each field.
            mRow.FKey = string.Empty;
            mRow.FValue = string.Empty;
        }
        public bool RowAdd()
        {
            if (FindPrimaryKey(mRow.FKey))
            {
                SetLastError(enumErrorNo.ErrorFind, "Duplicated key=" + mRow.FKey);
                return false;
            }

            mRowDB = mTableDB.NewTKeyValueRow();
            RowFlush();
            mTableDB.AddTKeyValueRow(mRowDB);
            return true; 
        }
        public bool SearchDataView(string sRowFilter, string sSort)
        {
            try
            {
                mDataView = mTableDB.DefaultView;
                mTableDB.DefaultView.RowFilter = sRowFilter;
                mTableDB.DefaultView.Sort = sSort;
                return true;
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
        }
        public bool RowFetch()
        {
            if (mRowDB == null)
                return false;

            mRow.ItemArray = mRowDB.ItemArray;
            myRowBackup();
            return true;
        }
        private void myRowBackup()
        {
            if (mRowDB == null)
                return;
            if (mRowBackup == null)
                return;
            mRowBackup.ItemArray = mRowDB.ItemArray;
        }
        public bool RowFlush()
        {
            if (mRow == null)
                return false;

            mRowDB.ItemArray = mRow.ItemArray;
            return true;
        }
        
        public bool RowRestore()
        {
            // primary key can NOT be DBNull! But we can only test any other field here.
            if ((mRowBackup == null) || (mRowBackup.IsFValueNull()))
            {
                RowClear();
            }
            else
            {
                mRow.ItemArray = mRowBackup.ItemArray;
            }
            return true;
        }

        public bool RowSelect()
        {
            DataRow[] rowsFind;
            string sFilter;
            try
            {
                sFilter = string.Format("FKey='{0}'", mRow.FKey);
                rowsFind = mTableDB.Select(sFilter);
                if (rowsFind.Length > 0)
                {
                    mRowDB = rowsFind[0] as DataSetKeyValue.TKeyValueRow;
                    return true;
                }
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
            return false;
        }

        bool RowCheckUpdate()
        {
            if ((mRowDB == null) || (mRowDB.FKey == null))
            {
                SetLastError("ERROR: Please SelectRow() first!");
                return false;
            }
            if (mRowDB.FKey != mRow.FKey)
            {
                SetLastError("ERROR: Primary key can NOT be changed..");
                return false;
            }

            // Verify dirty-update by check the whole row data or the field LastUpdateTime in last selected record.
            if (RowSelect())
                if (mRowDB.FValue == mRowBackup.FValue)  // verify by the whole row!
                    return true;
                else
                    SetLastError(enumErrorNo.ErrorNotFind, "ERROR: Record has changed since last read by other user.");
            else
                SetLastError(enumErrorNo.ErrorNotFind, "ERROR: Record is deleted since last read by other user.");

            return false;
        }
        public bool RowUpdate()
        {
            if (RowCheckUpdate())
            {
                if (RowFlush())
                {
                    myRowBackup();
                    return true;
                }
            }
            return false;
        }
        public bool RowDelete()
        {
            if (RowCheckUpdate())
            {
                mRowDB.Delete();
                //RowClear();
                //myRowBackup();  
            }
            return true;
        }

        public bool FindPrimaryKey(string sKey)
        {
            try
            {
                // contains() will raise exception if there's no PK fields.
                if (mTableDB.Rows.Contains(sKey))
                    return true;
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
            return false;
        }

        public bool HasChanges()
        {
            return mDataSetDB.HasChanges();
        }

    }
}
